/* -*- C++ -*- */

/****************************************************************************
** Copyright (c) quickfixengine.org  All rights reserved.
**
** This file is part of the QuickFIX FIX Engine
**
** This file may be distributed under the terms of the quickfixengine.org
** license as defined by quickfixengine.org and appearing in the file
** LICENSE included in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.quickfixengine.org/LICENSE for licensing information.
**
** Contact ask@quickfixengine.org if any conditions of this licensing are
** not clear to you.
**
****************************************************************************/

#ifndef PARSER_H
#define PARSER_H

#ifdef _MSC_VER
#pragma warning( disable : 4503 4355 4786 4290 )
#endif

#include "Exceptions.h"
#include <vector>
#include <iostream>
#include <string>
#include "Message.h"
#include "DataDictionary.h"
#include <vector>
#include <map>
#include <deque>

typedef std::map < std::string, FIX::Message > MessageFactory;
typedef std::map < std::string, int > Msg2TemplateId;
typedef std::map < int, std::string > TemplateId2Msg;
typedef std::vector<FastTag> FastTagVector;
typedef std::map < std::string, FastTagVector > TID2OrderedFields;



namespace FIX
{
/// Parses %FIX, FAST, HTTP messages off an input stream.
class Parser
{

public:
	class iMsg
{
public:
	iMsg()
	{
	}
	iMsg(const iMsg& copy)
	{
		_len = copy._len;
		memcpy(_msg, copy._msg, _len);
	}
	iMsg(const std::string &str)
	{
		_len = str.length();
		memcpy(_msg, str.c_str(), _len);
	}
	iMsg(const char* msg, size_t len)
	{
		_len = len;
		memcpy(_msg, msg, len);
	}
	size_t length() const
	{
		return _len;
	}
	const char* c_str() const
	{
		return _msg;
	}
	const unsigned char* c_ustr() const
	{
		return (const unsigned char*)_msg;
	}
	size_t _len;
	char _msg[64*1024];
};
//typedef std::deque<FMSG> FMSGQ;
typedef std::deque<iMsg, ALLOCATOR<iMsg> >	  Queue;

//typedef std::deque<std::string, ALLOCATOR<std::string> >	  Queue;
  
	Parser()
  : m_bufferSize( 0 ), m_sendLength(0), m_bufferSizeYetToRead(0), m_lenSizeYetToRead(0) {}
  virtual ~Parser() {}

  virtual bool extractLength( int& length, std::string::size_type& pos,
                      const std::string& buffer )  throw ( MessageParseError ) = 0;
  
  virtual bool readMessage( std::string& str )  throw ( MessageParseError ) = 0;
  virtual void readFromStream( int  m_socket) throw ( SocketRecvFailed ) = 0;
  
  virtual void writeMessage( const std::string& str )  throw ( MessageParseError ) = 0;
  virtual bool writeToStream( int  m_socket) throw ( SocketRecvFailed ) = 0;

  virtual void readFromStream( int  m_socket,  sockaddr_in &addr) throw ( SocketRecvFailed ) = 0;
  virtual bool writeToStream( int  m_socket, const sockaddr_in &addr) throw ( SocketRecvFailed ) = 0;

  Queue::size_type size() 
  {
	  return m_sendQueue.size();
  }

  virtual void setFactory(MessageFactory* messageFactory)
  {
	  m_MsgFactory = messageFactory;
  }
  virtual void setTemplateId2Message(TemplateId2Msg* TemplateId2Message)
  {
	  m_TemplateId2Message = TemplateId2Message;
  }
  virtual void setMessage2TemplateId(Msg2TemplateId* Message2TemplateId)
  {
	  m_Message2TemplateId = Message2TemplateId;
  }
  virtual void setDataDictionary(DataDictionary* dataDictionary)
  {
	  m_dataDictionary = dataDictionary;
  }
  virtual Queue& getQueue()
  {
	  return m_sendQueue;
  }
  virtual  const Queue& getQueue() const
  {
	  return m_sendQueue;
  }

  virtual void reset( void )
  {
  }

protected:
  std::string m_buffer;
  int m_bufferSize;
  unsigned int m_sendLength;
  int m_bufferSizeYetToRead;
  int m_lenSizeYetToRead;
  char m_sockbuffer[64*1024];
  MessageFactory* m_MsgFactory;
  TemplateId2Msg* m_TemplateId2Message;
  Msg2TemplateId* m_Message2TemplateId;
  DataDictionary* m_dataDictionary;
  Queue m_sendQueue;
};
}
#endif //PARSER_H
